package com.youdoneed.user.publicservice;

import com.taobao.api.response.AlibabaAliqinFcSmsNumSendResponse;
import com.youdoneed.base.application.AppException;
import com.youdoneed.base.application.ResultMessage;
import com.youdoneed.base.common.JWTUtils;
import com.youdoneed.base.common.RSAEncryptor;
import com.youdoneed.base.common.RandomString;
import com.youdoneed.base.common.RsaKeySalt;
import com.youdoneed.base.pagination.Page;
import com.youdoneed.base.pagination.Paging;
import com.youdoneed.user.application.AppConfig;
import com.youdoneed.user.application.PhoneMessage;
import com.youdoneed.user.consts.UserConst;
import com.youdoneed.user.model.Location;
import com.youdoneed.user.model.Nation;
import com.youdoneed.user.user.UserService;
import com.youdoneed.user.user.UserServiceImpl;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author Ewing
 * @since 2017-04-21
 **/
@RestController
@RequestMapping("/public")
@Api(description = "通用方法")
public class PublicController {

    private static final Logger LOGGER = LoggerFactory.getLogger(PublicController.class);

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private PublicService publicService;

    @Autowired
    private UserService userService;

    /**
     * 获取服务器毫秒时间。
     */
    @RequestMapping(value = "/timeMillis", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "获取服务器毫秒时间")
    public ResultMessage<Long> timeMillis() {
        return new ResultMessage<>(System.currentTimeMillis());
    }

    /**
     * 获取动态密钥及加密盐。
     */
    @RequestMapping(value = "/rsaKeySalt", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "获取动态密钥及加密盐")
    public ResultMessage<RsaKeySalt> rsaKeySalt() {
        RsaKeySalt rsaKeySalt = RSAEncryptor.getPublicKeySalt();
        return new ResultMessage<>(rsaKeySalt);
    }

    /**
     * 更新Token。
     */
    @RequestMapping(value = "/refreshToken", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "更新Token", notes = "新token有效期一个月")
    public ResultMessage<String> refreshToken(@RequestHeader(UserConst.TOKEN_KEY) String token) {
        token = JWTUtils.putClaimsData(token, "exp", JWTUtils.oneMonthExp());
        return new ResultMessage<>(token);
    }

    /**
     * 发送短信验证码。 api地址： http://open.taobao.com/doc2/apiDetail?spm=0.0.0.0.D1PYJd&apiId=25450
     */
    @RequestMapping(value = "/sendMessageCode", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "发送短信验证码", notes = "发送短信验证码（registered表示是否已注册），失败返回code为5代表当前发送短信超过限制给个用户提示“您的操作过于频繁，请稍候再试")
    public ResultMessage<?> sendMessageCode(String phoneNo, Boolean registered, String nation) {
        if (phoneNo == null || !AppConfig.PHONE_NO_PATTERN.matcher(phoneNo).matches()) {
            throw new AppException("PhoneNumberFormatIncorrect");
        }

        if (registered != null && registered
                && userService.getUserByPhoneNo(phoneNo) == null) {
            throw new AppException("请先用该手机号注册。").setCode(2);
        }

        // 根据不同的国家发送短信
        boolean sendResult;
        //是否是发送的国际验证码
        boolean isNational;
        String resultJson;
        String code = RandomString.randomNumberString(6);
        AlibabaAliqinFcSmsNumSendResponse rsp;
        if (!StringUtils.hasText(nation) || "86".equals(nation)) {
            isNational = false;
            rsp = PhoneMessage.sendCheckCode(phoneNo, code);
            sendResult = rsp.isSuccess();
            resultJson = rsp.getBody();

        } else {
            isNational = true;
            resultJson = PhoneMessage.sendNationalCode(nation + phoneNo, code);
            sendResult = resultJson.contains("mterrcode=000");
        }
        LOGGER.info(resultJson);
        if (!sendResult) {
            if (!isNational){   //中国的短信
                if (resultJson.contains("BUSINESS_LIMIT_CONTROL")){
                    return new ResultMessage<>().toFailure("您的操作过于频繁，请稍候再试").setCode(5);
                }else if (resultJson.contains("MOBILE_NUMBER_ILLEGAL")){
                    return new ResultMessage<>().toFailure("手机号码格式错误").setCode(6);
                }else if (resultJson.contains("OUT_OF_SERVICE")){
                    return new ResultMessage<>().toFailure("业务停机").setCode(7);
                }else {
                    return new ResultMessage<>().toFailure("其他错误").setCode(8);
                }
            }else {             //国外短信
                if (resultJson.contains("0110")) {
                    return new ResultMessage<>().toFailure("您的操作过于频繁，请稍候再试").setCode(5);
                }else {
                    return new ResultMessage<>().toFailure("其他错误").setCode(8);
                }
            }
        }

        // 发送成功 保存到Redis 10分钟有效
        redisTemplate.opsForValue().set("loginCode" + nation + phoneNo, code, 10, TimeUnit.MINUTES);
        return new ResultMessage<>();
    }

    /**
     * 假装发送短信验证码。
     */
    @RequestMapping(value = "/feignSendMessageCode", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation("假装发送短信验证码（该接口仅供手工测试）")
    public ResultMessage<String> feignSendMessageCode(String phoneNo, String nation) {
        if (phoneNo == null || !AppConfig.PHONE_NO_PATTERN.matcher(phoneNo).matches()) {
            throw new AppException("PhoneNumberFormatIncorrect");
        }
        String code = RandomString.randomNumberString(6);
        // 发送成功 保存到Redis 10分钟有效
        redisTemplate.opsForValue().set("loginCode" + nation + phoneNo, code, 10, TimeUnit.MINUTES);
        return new ResultMessage<>(code);
    }

    /**
     * 获取国家列表。
     */
    @ApiOperation("获取国家列表（流式获取时count请传false）")
    @RequestMapping(value = "/getNations", method = {RequestMethod.GET, RequestMethod.POST})
    public ResultMessage<Page<Nation>> getNations(Paging paging) {
        return new ResultMessage<>(publicService.getNations(paging));
    }

    /**
     * 根据上级区域ID获取下级区域名称，例如86为获取中国的省份。
     */
    @ApiOperation("根据上级区域ID获取下级区域名称，例如86为获取中国的省份")
    @RequestMapping(value = "/subLocations", method = {RequestMethod.GET, RequestMethod.POST})
    public ResultMessage<List<Location>> subLocations(String parentId) {
        return new ResultMessage<>(publicService.subLocations(parentId));
    }

}
